/*
 * GenFrame.java
 *
 * Created on 30.11.2010, 0:09:09
 */

package gen_seq.ui;

import gen_seq.export.ChromosomeToFileExporter;
import gen_seq.generator.Population;
import java.awt.Color;
import java.awt.EventQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
import javax.swing.table.*;
import java.util.*;


/**
 *
 * @author akademi4eg
 */
public class GenFrame extends JFrame {

    /** Creates new form GenFrame */
    public GenFrame() {
        initComponents();
        Random rand = new Random();
        setLocation(rand.nextInt(300), rand.nextInt(100));
    }

    public void lockElementsDueToLaunch ()
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run() {
                mItemLaunch.setEnabled(false);
                mItemPause.setEnabled(true);
                mItemStop.setEnabled(true);
                mItemExport.setEnabled(true);
            }
        });
    }

    public void unlockElementsDueToLaunch ()
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run() {
                mItemLaunch.setEnabled(true);
                mItemPause.setText("Pause");
                mItemPause.setEnabled(false);
                mItemStop.setEnabled(false);
            }
        });
    }

    public void updateStats (final int type, final String value)
    {
        EventQueue.invokeLater(new Runnable(){
            public void run() {
                switch (type)
                {
                    case StatsCollector.POPULATION_LENGTH:
                        lblPopLen.setText(value);
                        break;
                    case StatsCollector.CHROMOSOME_LENGTH:
                        lblChrLen.setText(value);
                        break;
                    case StatsCollector.POPULATION_AGE:
                        lblPopAge.setText(value);
                        break;
                    case StatsCollector.AVG_RATE:
                        lblRate.setText(value);
                        break;
                    case StatsCollector.BEST_ACHIEVEMENT:
                        lblBestAch.setText(value);
                        break;
                    default:
                        // we should never come here
                        throw new TypeNotPresentException("Wrong stat stype.", null);
                }
            }
        });
    }

    public void initStatsTable (int row_num)
    {
        DefaultTableModel tmodel = (DefaultTableModel) chrsStats.getModel();
        tmodel.setRowCount(row_num);
    }

    public void updateStatsTableRow (int chr_id, double avg, double fit, Color col)
    {
        DefaultTableModel tmodel = (DefaultTableModel) chrsStats.getModel();
        tmodel.setValueAt(chr_id+1, chr_id, 0);
        tmodel.setValueAt(avg, chr_id, 1);
        tmodel.setValueAt(fit, chr_id, 2);
        // XXX refactor
        if (col != null)
        {
            String col_str;
            if (col.equals(Color.red))
                col_str = "red";
            else if (col.equals(Color.green))
                col_str = "green";
            else if (col.equals(Color.blue))
                col_str = "blue";
            else if (col.equals(Color.orange))
                col_str = "orange";
            else if (col.equals(Color.magenta))
                col_str = "magenta";
            else
                col_str = "";
            tmodel.setValueAt(col_str, chr_id, 3);
        }
    }

    public void drawCorrsPlotAxis (double minY, double maxY, int minX, int maxX)
    {
        ((PlotPanel) corrsPlot).setAxis(minY, maxY, minX, maxX);
    }

    public void drawCorrCurve (java.awt.Color col, LinkedList<CorrPoint> pts)
    {
        ((PlotPanel) corrsPlot).setCurve(col, pts);
        corrsPlot.repaint();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        statsPanel = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        lblPopLen = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        lblChrLen = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        lblPopAge = new javax.swing.JLabel();
        jLabel4 = new javax.swing.JLabel();
        lblRate = new javax.swing.JLabel();
        jLabel5 = new javax.swing.JLabel();
        lblBestAch = new javax.swing.JLabel();
        chrsStatsPane = new javax.swing.JScrollPane();
        chrsStats = new javax.swing.JTable();
        corrsPlot = new PlotPanel();
        mainMenu = new javax.swing.JMenuBar();
        menuRun = new javax.swing.JMenu();
        mItemLaunch = new javax.swing.JMenuItem();
        mItemStop = new javax.swing.JMenuItem();
        mItemPause = new javax.swing.JMenuItem();
        jSeparator2 = new javax.swing.JPopupMenu.Separator();
        mItemExport = new javax.swing.JMenuItem();
        jSeparator1 = new javax.swing.JPopupMenu.Separator();
        Exit = new javax.swing.JMenuItem();
        menuOptions = new javax.swing.JMenu();
        mItemChangeMutRate = new javax.swing.JMenuItem();
        menuHelp = new javax.swing.JMenu();
        mItemAbout = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("GA sequences generator");
        setMinimumSize(new java.awt.Dimension(465, 292));

        statsPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Statistics"));

        jLabel1.setFont(new java.awt.Font("Dialog", 0, 10));
        jLabel1.setText("Population length:");

        lblPopLen.setFont(new java.awt.Font("Dialog", 0, 10));
        lblPopLen.setText("n/a");

        jLabel2.setFont(new java.awt.Font("Dialog", 0, 10));
        jLabel2.setText("Chromosome length:");

        lblChrLen.setFont(new java.awt.Font("Dialog", 0, 10));
        lblChrLen.setText("n/a");

        jLabel3.setFont(new java.awt.Font("Dialog", 0, 10));
        jLabel3.setText("Population age:");

        lblPopAge.setFont(new java.awt.Font("Dialog", 0, 10));
        lblPopAge.setText("0");

        jLabel4.setFont(new java.awt.Font("Dialog", 0, 10));
        jLabel4.setText("Mutation rate:");

        lblRate.setFont(new java.awt.Font("Dialog", 0, 10));
        lblRate.setText("n/a");

        jLabel5.setFont(new java.awt.Font("Dialog", 0, 10));
        jLabel5.setText("Best achievement:");

        lblBestAch.setFont(new java.awt.Font("Dialog", 0, 10));
        lblBestAch.setText("n/a");

        javax.swing.GroupLayout statsPanelLayout = new javax.swing.GroupLayout(statsPanel);
        statsPanel.setLayout(statsPanelLayout);
        statsPanelLayout.setHorizontalGroup(
            statsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(statsPanelLayout.createSequentialGroup()
                .addGroup(statsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel1, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jLabel2, javax.swing.GroupLayout.Alignment.TRAILING))
                .addGap(2, 2, 2)
                .addGroup(statsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addGroup(statsPanelLayout.createSequentialGroup()
                        .addComponent(lblPopLen)
                        .addGap(18, 18, 18)
                        .addComponent(jLabel3))
                    .addGroup(statsPanelLayout.createSequentialGroup()
                        .addComponent(lblChrLen)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(jLabel4)))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(statsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(statsPanelLayout.createSequentialGroup()
                        .addComponent(lblPopAge)
                        .addGap(27, 27, 27)
                        .addComponent(jLabel5)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(lblBestAch))
                    .addComponent(lblRate))
                .addContainerGap(182, Short.MAX_VALUE))
        );
        statsPanelLayout.setVerticalGroup(
            statsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(statsPanelLayout.createSequentialGroup()
                .addGroup(statsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(statsPanelLayout.createSequentialGroup()
                        .addGroup(statsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(lblPopLen)
                            .addComponent(jLabel1))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(statsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jLabel2)
                            .addComponent(lblChrLen)
                            .addComponent(jLabel4)
                            .addComponent(lblRate)))
                    .addGroup(statsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                        .addComponent(jLabel3)
                        .addComponent(lblPopAge)
                        .addComponent(jLabel5)
                        .addComponent(lblBestAch)))
                .addContainerGap(14, Short.MAX_VALUE))
        );

        chrsStatsPane.setPreferredSize(new java.awt.Dimension(256, 212));

        chrsStats.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {
                "Chr#", "Avg", "Fitness", "Color"
            }
        ) {
            Class[] types = new Class [] {
                java.lang.Integer.class, java.lang.Double.class, java.lang.Double.class, java.lang.String.class
            };
            boolean[] canEdit = new boolean [] {
                false, false, false, false
            };

            public Class getColumnClass(int columnIndex) {
                return types [columnIndex];
            }

            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit [columnIndex];
            }
        });
        chrsStats.getTableHeader().setReorderingAllowed(false);
        chrsStatsPane.setViewportView(chrsStats);
        chrsStats.getColumnModel().getColumn(1).setResizable(false);
        chrsStats.getColumnModel().getColumn(2).setResizable(false);
        chrsStats.getColumnModel().getColumn(3).setResizable(false);

        corrsPlot.setBackground(new java.awt.Color(255, 255, 255));

        javax.swing.GroupLayout corrsPlotLayout = new javax.swing.GroupLayout(corrsPlot);
        corrsPlot.setLayout(corrsPlotLayout);
        corrsPlotLayout.setHorizontalGroup(
            corrsPlotLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 294, Short.MAX_VALUE)
        );
        corrsPlotLayout.setVerticalGroup(
            corrsPlotLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 210, Short.MAX_VALUE)
        );

        menuRun.setText("Run");

        mItemLaunch.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_L, java.awt.event.InputEvent.CTRL_MASK));
        mItemLaunch.setText("Launch...");
        mItemLaunch.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                mItemLaunchActionPerformed(evt);
            }
        });
        menuRun.add(mItemLaunch);

        mItemStop.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S, java.awt.event.InputEvent.CTRL_MASK));
        mItemStop.setText("Stop");
        mItemStop.setEnabled(false);
        mItemStop.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                mItemStopActionPerformed(evt);
            }
        });
        menuRun.add(mItemStop);

        mItemPause.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_P, java.awt.event.InputEvent.CTRL_MASK));
        mItemPause.setText("Pause");
        mItemPause.setEnabled(false);
        mItemPause.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                mItemPauseActionPerformed(evt);
            }
        });
        menuRun.add(mItemPause);
        menuRun.add(jSeparator2);

        mItemExport.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_E, java.awt.event.InputEvent.CTRL_MASK));
        mItemExport.setText("Export...");
        mItemExport.setEnabled(false);
        mItemExport.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                mItemExportActionPerformed(evt);
            }
        });
        menuRun.add(mItemExport);
        menuRun.add(jSeparator1);

        Exit.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_Q, java.awt.event.InputEvent.CTRL_MASK));
        Exit.setText("Quit");
        Exit.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                ExitActionPerformed(evt);
            }
        });
        menuRun.add(Exit);

        mainMenu.add(menuRun);

        menuOptions.setText("Options");

        mItemChangeMutRate.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_R, java.awt.event.InputEvent.CTRL_MASK));
        mItemChangeMutRate.setText("Evolution parameters...");
        mItemChangeMutRate.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                mItemChangeMutRateActionPerformed(evt);
            }
        });
        menuOptions.add(mItemChangeMutRate);

        mainMenu.add(menuOptions);

        menuHelp.setText("Help");

        mItemAbout.setText("About...");
        mItemAbout.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                mItemAboutActionPerformed(evt);
            }
        });
        menuHelp.add(mItemAbout);

        mainMenu.add(menuHelp);

        setJMenuBar(mainMenu);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addComponent(chrsStatsPane, javax.swing.GroupLayout.PREFERRED_SIZE, 256, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(corrsPlot, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
            .addComponent(statsPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(statsPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(corrsPlot, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(chrsStatsPane, javax.swing.GroupLayout.DEFAULT_SIZE, 210, Short.MAX_VALUE)))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void ExitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ExitActionPerformed
        System.exit(0);
    }//GEN-LAST:event_ExitActionPerformed

    private void mItemLaunchActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mItemLaunchActionPerformed
       if (launchDialog == null)
       {
           launchDialog = new launcherDialog(this, true);
           launchDialog.setLocationRelativeTo(this);
       }
       launchDialog.setVisible(true);
    }//GEN-LAST:event_mItemLaunchActionPerformed

    private void mItemPauseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mItemPauseActionPerformed
        final boolean isActive = Population.getInstance().isActive();
        Population.getInstance().setActive(!isActive);
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                mItemPause.setText(!isActive?"Pause":"Resume");
            }
        });
    }//GEN-LAST:event_mItemPauseActionPerformed

    private void mItemStopActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mItemStopActionPerformed
        Population.getInstance().setActive(false);
        Population.getInstance().setRunning(false);
    }//GEN-LAST:event_mItemStopActionPerformed

    private void mItemAboutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mItemAboutActionPerformed
        JOptionPane.showMessageDialog(this, "Sequences generator based on genetic algorythm. Version "
                +Main.version+"."+System.getProperty("line.separator")+"Distributed under GNU GPLv2."+System.getProperty("line.separator")+"Developed in 2010-2011 by Dmytro Tkanov.", "About sequences generator", JOptionPane.INFORMATION_MESSAGE);
    }//GEN-LAST:event_mItemAboutActionPerformed

    private void mItemChangeMutRateActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mItemChangeMutRateActionPerformed
       if (mutationDialog == null)
       {
           mutationDialog = new mutationRateDialog(this, true);
           mutationDialog.setLocationRelativeTo(this);
       }
       else
       {
           ((mutationRateDialog) mutationDialog).fillValues();
       }
       mutationDialog.setVisible(true);
    }//GEN-LAST:event_mItemChangeMutRateActionPerformed

    private void mItemExportActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mItemExportActionPerformed
        new Thread(new Runnable() {
            public void run() {
                try {
                    boolean active_state = Population.getInstance().isActive();
                    Population.getInstance().setActive(false);
                    ChromosomeToFileExporter exporter = new ChromosomeToFileExporter();
                    Population.getInstance().getEvolutionKeeper().acquire();
                    exporter.setData(Population.getInstance().getBestAchievement());
                    exporter.setName("exported_chromosome");
                    exporter.run();
                    Population.getInstance().getEvolutionKeeper().release();
                    Population.getInstance().setActive(active_state);
                } catch (InterruptedException ex) {
                    Logger.getLogger(GenFrame.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }).start();
    }//GEN-LAST:event_mItemExportActionPerformed

    private JDialog launchDialog;
    private JDialog mutationDialog;
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JMenuItem Exit;
    private javax.swing.JTable chrsStats;
    private javax.swing.JScrollPane chrsStatsPane;
    private javax.swing.JPanel corrsPlot;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JPopupMenu.Separator jSeparator1;
    private javax.swing.JPopupMenu.Separator jSeparator2;
    private javax.swing.JLabel lblBestAch;
    private javax.swing.JLabel lblChrLen;
    private javax.swing.JLabel lblPopAge;
    private javax.swing.JLabel lblPopLen;
    private javax.swing.JLabel lblRate;
    private javax.swing.JMenuItem mItemAbout;
    private javax.swing.JMenuItem mItemChangeMutRate;
    private javax.swing.JMenuItem mItemExport;
    private javax.swing.JMenuItem mItemLaunch;
    private javax.swing.JMenuItem mItemPause;
    private javax.swing.JMenuItem mItemStop;
    private javax.swing.JMenuBar mainMenu;
    private javax.swing.JMenu menuHelp;
    private javax.swing.JMenu menuOptions;
    private javax.swing.JMenu menuRun;
    private javax.swing.JPanel statsPanel;
    // End of variables declaration//GEN-END:variables

}
